package webapi

import (
	"MqttCloudProtocolServer/publiclib/helplib"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/wonderivan/logger"
)

//ServiceControlService 服务控制类
type UpdateGatewayService struct {
	base ServiceBase
}

//Regist 注册
func (_this *UpdateGatewayService) Regist(mux *http.ServeMux) {
	_this.base.Regist(mux)
	_this.base.path += "ota"

	//"process_statue","daemon_statue","start_all","stop_all","start_daemon","stop_daemon","star_process","stop_process"
	_this.base.HandleRegist("checkupdate", _this.checkUpdate)
	_this.base.HandleRegist("getFile", _this.getFile)
	//_this.base.HandleRegist("addGateways", _this.addGateway)
	//_this.base.HandleRegist("saveConfig", _this.saveConfig)
}

type AppList struct {
	SourceFile string `json:"url"`
	TargetFile string `json:"file_name"`
}
type UpdateStructure struct {
	OtaEnable    bool       `json:"ota"`
	OtaUrl1      string     `json:"url1"`
	OtaUrl2      string     `json:"url2"`
	AppEnable    bool       `json:"app"`
	Appurls      []*AppList `json:"appurl"`
	ConfigEnable bool       `json:"config"`
	CfgUrl       string     `json:"cfgurl"`
}
type UpdateFileInfo struct {
	Fwver    string            `json:"fwver"`
	Fwfile1  string            `json:"fwfile1"`
	Fwfile2  string            `json:"fwfile2"`
	CfgInfos []*CfgInfosStruct `json:"cfgs"`
	Product  string            `json:"product"`
	Appver   string            `json:"appver"`
	Appfiles []*AppList        `json:"appfiles"`
}
type CfgInfosStruct struct {
	Template string `json:"template"`
	Cfgver   string `json:"cfgver"`
	Cfgfile  string `json:"cfgfile"`
}

//AddGateway 增加一个网关连接请求
func (_this *UpdateGatewayService) checkUpdate(w http.ResponseWriter, r *http.Request) {
	vars := r.URL.Query()
	prifix := "http://"
	if r.TLS != nil {
		prifix = "https://"
	}
	if len(vars) > 0 {
		product := GetParam(vars, "product")
		fwVersion := GetParam(vars, "fwver")
		cfgVersion := GetParam(vars, "cfgver")
		appVersion := GetParam(vars, "appver")
		template := GetParam(vars, "template")
		fmt.Println(product, fwVersion, cfgVersion, appVersion, template)
		if res, err := helplib.FileExists("update/" + product + ".cfg"); res && err == nil {
			updateInfo := new(UpdateStructure)
			updateInfo.OtaEnable = false
			updateInfo.AppEnable = false
			updateInfo.ConfigEnable = false
			if buffer, err := ioutil.ReadFile("update/" + product + ".cfg"); err != nil {
				fmt.Fprintln(w, "{\"message\":\"服务列表读取错误\"}")
				logger.Error("服务列表读取错误" + err.Error())
			} else {
				updateFileInfo := new(UpdateFileInfo)
				if err = json.Unmarshal(buffer, updateFileInfo); err != nil {
					fmt.Fprintln(w, "{\"message\":\"服务列表读取错误\"}")
					logger.Error("服务列表读取错误")
				} else {
					host := ""
					if thost, err := ioutil.ReadFile("config/host"); err != nil {
						//fmt.Fprintln(w, "{\"message\":\"主机读取错误\"}")
						logger.Error("主机读取错误" + err.Error())
						host = r.Host
					} else {
						host = string(thost)
					}
					if updateFileInfo.Product != product {
						fmt.Fprintln(w, "{\"message\":\"product error\"}")
						return
					}
					if strings.TrimSpace(template) != "" && updateFileInfo.CfgInfos != nil {
						for _, cfg := range updateFileInfo.CfgInfos {
							if template == cfg.Template {
								updateInfo.ConfigEnable = cfg.Cfgver != cfgVersion
								res, err = helplib.FileExists(cfg.Cfgfile)
								if res && err == nil {
									updateInfo.CfgUrl = prifix + host + "/Service/ota/getFile/" + cfg.Cfgfile + "?type=cfg"
								} else {
									updateInfo.CfgUrl = ""
								}
							}
						}
					}
					updateInfo.OtaEnable = updateFileInfo.Fwver != fwVersion
					if updateInfo.OtaEnable {
						res, err := helplib.FileExists(updateFileInfo.Fwfile1)
						if res && err == nil {
							updateInfo.OtaUrl1 = prifix + host + "/Service/ota/getFile/" + updateFileInfo.Fwfile1 + "?type=ota"
						} else {
							updateInfo.OtaUrl1 = ""
						}
						res, err = helplib.FileExists(updateFileInfo.Fwfile2)
						if res && err == nil {
							updateInfo.OtaUrl2 = prifix + host + "/Service/ota/getFile/" + updateFileInfo.Fwfile2 + "?type=ota"
						} else {
							updateInfo.OtaUrl2 = ""
						}
					} else {
						updateInfo.OtaUrl1 = ""
					}
					updateInfo.AppEnable = updateFileInfo.Appver != appVersion
					if updateInfo.AppEnable {
						updateInfo.Appurls = updateFileInfo.Appfiles
						//var willRemoveDic []int = arr1[start:end]
						passCount := 0
						for i, v := range updateInfo.Appurls {
							res, err = helplib.FileExists(v.SourceFile)
							if res && err == nil {
								updateInfo.Appurls[i-passCount].SourceFile = prifix + host + "/Service/ota/getFile/" + v.SourceFile + "?type=app"
								updateInfo.Appurls[i-passCount].TargetFile = v.TargetFile
							} else {
								passCount++
							}
							updateInfo.Appurls = updateInfo.Appurls[:len(updateInfo.Appurls)-passCount]
						}
					} else {
						updateInfo.Appurls = nil
					}
					if buffer, err := json.Marshal(updateInfo); err == nil {
						fmt.Fprintln(w, string(buffer))
						return
					} else {
						fmt.Fprintln(w, "{\"message\":\"unknown error\"}")
						return
					}
				}
			}
		} else {
			fmt.Fprintln(w, "{\"message\":\"no update info\"}")
			return
		}
	}
}

//AddGateway 增加一个网关连接请求
func (_this *UpdateGatewayService) getFile(w http.ResponseWriter, r *http.Request) {
	vars := r.URL.Query()
	path := r.URL.Path
	path = strings.Replace(path, "/Service/ota/getFile/", "", 1)
	if len(vars) > 0 {
		if res, err := helplib.FileExists(path); !res || err != nil {
			fmt.Fprintln(w, "{\"message\":\"file not exist\"}")
			return
		}
		otype := GetParam(vars, "type")
		switch otype {
		case "app", "ota":
			_this.downloadFile(path, w)
		case "cfg":
			_this.getCfgJson(path, w)
		default:
			fmt.Fprintln(w, "{\"message\":\"type not support\"}")
		}
		return
	}
}

func (*UpdateGatewayService) downloadFile(path string, w http.ResponseWriter) {
	file, _ := os.Open(path)
	defer file.Close()

	fileHeader := make([]byte, 512)
	_, err := file.Read(fileHeader)
	if err != nil {
		fmt.Fprintln(w, "{\"message\":\"file read error\"}")
	}

	//fileStat, err := file.Stat()
	//if err != nil {
	//	fmt.Fprintln(w, "{\"message\":\"file read error\"}")
	//}
	_, fname := filepath.Split(path)
	w.Header().Set("Content-Disposition", "attachment; filename="+fname)
	w.Header().Set("Content-Type", http.DetectContentType(fileHeader))
	//w.Header().Set("Content-Length", strconv.FormatInt(fileStat.Size(), 10))

	file.Seek(0, 0)
	io.Copy(w, file)
}

func (*UpdateGatewayService) getCfgJson(path string, w http.ResponseWriter) {
	file, _ := os.Open(path)
	defer file.Close()

	fileStat, _ := file.Stat()

	fileContent := make([]byte, fileStat.Size())
	_, err := file.Read(fileContent)
	s := string(fileContent)
	if err != nil {
		fmt.Fprintln(w, "{\"message\":\"file read error\"}")
	}

	w.Header().Set("Content-Disposition", "inline")
	w.Header().Set("Content-Type", "application/json")
	//w.Header().Set("Content-Length", strconv.FormatInt(fileStat.Size(), 10))

	//file.Seek(0, 0)
	fmt.Fprintln(w, s)
}
